package com.bigShen.pattern.prototype.reflectClone;

import com.bigShen.pattern.prototype.JinGuBang;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Auther: lei.shen
 * @Date: 2018/9/24 19:06
 * @Description:
 */
public class ReflectQiTianDaSheng extends Monkey implements Cloneable{

    private String type;

    private String name;

    private JinGuBang jinGuBang;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public JinGuBang getJinGuBang() {
        return jinGuBang;
    }

    public void setJinGuBang(JinGuBang jinGuBang) {
        this.jinGuBang = jinGuBang;
    }


    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this.reflectClone();
    }

    private Object reflectClone() {

        try {
            ReflectQiTianDaSheng clone = this.getClass().newInstance();

            Field[] fields = this.getClass().getFields();
            Field[] declaredFields = this.getClass().getDeclaredFields();
            Field[] parentFields = new Field[]{};
            Field[] parentDeclaredFields = new Field[]{};
            if (null != this.getClass().getSuperclass()) {
                parentFields = this.getClass().getSuperclass().getFields();
                parentDeclaredFields = this.getClass().getSuperclass().getDeclaredFields();
            }

            Set<Field> fieldSet = new HashSet<Field>();
            fieldSet.addAll(Arrays.asList(fields));
            fieldSet.addAll(Arrays.asList(declaredFields));
            fieldSet.addAll(Arrays.asList(parentFields));
            fieldSet.addAll(Arrays.asList(parentDeclaredFields));
            List<Field> fieldList = new ArrayList<Field>(fieldSet);

            for (Field field : fieldList) {

                String fieldName = field.getName();
                String firstLetter = fieldName.substring(0, 1).toUpperCase();
                String otherLetter = fieldName.substring(1, fieldName.length());
                String getMethodStr = "get" + firstLetter + otherLetter;
                String setMethodStr = "set" + firstLetter + otherLetter;

                Method getMethod = this.getClass().getMethod(getMethodStr);
                Method setMethod = this.getClass().getMethod(setMethodStr, field.getType());

                Object value = getMethod.invoke(this);
                setMethod.invoke(clone, value);

            }
            return clone;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return null;
    }

}
